In [1]:
#!/usr/bin/python
#-*- coding: utf-8 -*-

基于最优化方法的最佳回归系数确定

优点:计算代价不高,易于理解和实现
缺点:容易欠拟合,分类精度可能不高
适用数据类型:数值型、标称型

二分类Sigmoid函数

Sigmoid函数

$$\sigma (z)=\frac{1}{1+e^{-z}}$$
  

sigmoid
类似阶跃函数,而阶跃函数的瞬间跳跃过程在数学上比较难处理
sigmoid函数在z=0处的取值为0.5,取值范围为0-1
因此可以将\(\sigma (z) < 0.5\)的结果归为分类0,将\(\sigma (z) > 0.5\)的结果归类为分类1

Logistic回归

为每个特征\(x_i\)分配一个回归系数(权重)\(wi\)
只需计算\(\sigma (\sum^{n}
{i=0} {w_i \cdot x_i})\),若小于0.5则分为类0,若大于0.5则分为类1
记\(z = w_0x_0 + w_1x_1 + w_2x_2 + ... = w^Tx\)
其中最重要的是找到回归系数

基于最优化方法的最佳回归系数确定

梯度上升法:查找局部最大值,沿梯度方向探寻,不断逼近实际的最大值
函数\(f(x,y)\)的梯度记为
$$\triangledown f(x,y) = \left( \begin{array}{ccc} \frac{\partial f(x,y)}{\partial x} \\\ \frac{\partial f(x,y)}{\partial y} \end{array} \right)$$
梯度上升算法的迭代公式
$$w := w + \alpha \triangledown_w f(w)$$
其中,w为回归系数向量,\(\alpha\)为步长,\(\triangledown_w\)为梯度,f(w)为待求最大值的函数
类似的,梯度下降算法的迭代公式为\(w := w + \alpha \triangledown_w f(w)\),用于毕竟最小值
通常采用迭代的方式,直到达到某个条件(如迭代次数达到某个值,或算法达到某个误差范围内)为止

举例(限定迭代次数)

已知一组100个的数据,共3个特征值,构成100x3的矩阵D;以及一组对应的二分类标签向量F(元素为0或1,长度100,假设是列向量)

  • 选择算法步长\(\alpha\)和迭代次数n
  • 初始化一个回归系数行向量w(通常将各个元素初始化为1)
  • 重复n次
    • 根据w计算D和F构成的数据集的梯度
      • 根据w对D每行进行加权求和
        $$D \times w$$
      • 利用sigmoid函数对加权求和的结果进行分类,得到各组的sigmoid值组成的列向量S
      • 计算梯度(误差) $$E = F - S$$
        由于sigmoid函数并不是理想的阶跃函数,其值不完全是0或1,存在一定的误差
    • 迭代计算新的回归系数w $$w := w + \alpha \times D^T \times E$$
  • 得到最后的回归系数w
In [26]:
import logRegres
In [27]:
dataArr, labelMat = logRegres.loadDataSet()
In [34]:
weights = logRegres.gradAscent(dataArr, labelMat)
print weights
[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]
In [35]:
# numpy.martix的getA方法,将矩阵转换为对应的数组返回
logRegres.plotBestFit(weights.getA())

随机梯度上升算法

梯度上升算法每次更新回归系数都需要遍历一次数据集,当样本、特征数量比较庞大时,计算复杂度会变得非常高;
可以采用随机梯度上升算法代替,
随机梯度上升算法每次只用一个样本点来更新回归系数,可以在新样本到来时进行增量式的更新,是一种在线学习算法

In [36]:
weights = logRegres.stocGradAscent0(np.array(dataArr), labelMat)
logRegres.plotBestFit(weights)

分类效果并不是很好

但我们更关注的是——随机梯度上升算法是否收敛?
运行随机梯度上升算法进行多次迭代——
随机梯度上升算法多次迭代
总体上看,三个参数随迭代次数的增加收敛,而且参数X1和X2能较快收敛;
但曲线存在着明显的局部波动,这不是我们所期望的

改进的随机梯度上升算法

  • 动态变化的步长\( \alpha \)
    如取\( \alpha = \frac{4}{1+j+i} + 0.01 \)
    • 0.01为常数项,以确保\( \alpha \)永远不会减小到0,同时保证新加入的样本具有一定的影响,通常样本动态性越强,常数项就取得越大
    • 分子4是控制步长变化大小的因子
    • 分母中i为当前样本的索引号(初始0,每处理一个样本就加一)
    • 分母中j为当前迭代的索引号(初始0,每迭代一次就加一)
    • 分母同时受i和j控制,当\( j < max(i) \)时\( \alpha \)不会出现严格下降
      避免参数严格下降常见于模拟退火算法等其他优化算法
  • 随机取样
    • 避免相邻数据存在一定的相关性而出现周期性波动
In [37]:
weights = logRegres.stocGradAscent1(np.array(dataArr), labelMat)
logRegres.plotBestFit(weights)

分类效果比改进前好得多
已经很接近梯度上升算法,但计算量却要小的多~

改进后参数随迭代次数的变化:
改进的随机梯度上升算法多次迭代
可以看到,局部波动明显改善,而且收敛速度也更快

数据缺失处理

部分特征值缺失

  • 用可用特征的均值来填补缺失值
  • 使用特殊值如-1,0等来填补缺失值
    比如先前出现的梯度上升的迭代公式\(w := w + \alpha \triangledown_w f(w)\)
    缺失值如果填补特殊值0,则迭代公式对应项变为w := w,也即不影响回归系数的更新
  • 忽略有缺失值的样本
  • 使用相似样本的均值填补缺失值
  • 使用另外的机器学习算法预测缺失值

部分标签缺失

一般直接简单地把这些数据丢弃

In [ ]: